﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using sdd.subsystems.io;

namespace sdd.subsystems.display
{
    public class DisplayProxy : IDisplay
    {
        private IDisplay pDisplay;

        public DisplayProxy(IDisplay proxiedDisplay)
        {
            pDisplay = proxiedDisplay;
            pDisplay.KeypadEvent += PDisplay_KeypadEvent;
        }

        private void PDisplay_KeypadEvent(object sender, KeypadEventArgs e)
        {
            if (!InputDisabled)
            {
                ProxyKeypadEventPreviewArgs previewEvent = new ProxyKeypadEventPreviewArgs(e.Key);

                // raise preview event
                if (KeypadPreviewEvent != null) { KeypadPreviewEvent(this, previewEvent); }

                // should we filter the event?
                if (!previewEvent.Filter)
                {
                    // no, bubble up through proxy
                    if (KeypadEvent != null) { KeypadEvent(this, e); }
                }
            }
        }

        internal IDisplay ProxiedDisplay
        {
            get { return pDisplay; }
            set { pDisplay = value; }
        }

        public bool OutputDisabled { internal set; get; }
        public bool InputDisabled { internal set; get; }

        public ISerialIO Port
        {
            get
            {
                return pDisplay.Port;
            }

            set
            {
                pDisplay.Port = value;
            }
        }

        public object SyncLock
        {
            get
            {
                return pDisplay.SyncLock;
            }
        }

        public event EventHandler<KeypadEventArgs> KeypadEvent;

        internal event EventHandler<ProxyKeypadEventPreviewArgs> KeypadPreviewEvent; 

        public void ActivatePiezoBuzzer(short frequencyHz, short timeMilliseconds)
        {
            if (!OutputDisabled) { pDisplay.ActivatePiezoBuzzer(frequencyHz, timeMilliseconds); }
        }

        public void ClearScreen()
        {
            if (!OutputDisabled) { pDisplay.ClearScreen(); }
        }

        public void ClearTextWindow(byte windowId)
        {
            if (!OutputDisabled) { pDisplay.ClearTextWindow(windowId); }
        }

        public void DrawBar(byte top, byte left, byte height, byte maxWidth, byte percent)
        {
            if (!OutputDisabled) { pDisplay.DrawBar(top, left, height, maxWidth, percent); }
        }

        public void DrawFilledRectangle(byte fillColor, byte leftPos, byte topPos, byte rightPos, byte bottomPos)
        {
            if (!OutputDisabled) { pDisplay.DrawFilledRectangle(fillColor, leftPos, topPos, rightPos, bottomPos); }
        }

        public void DrawLine(byte startX, byte startY, byte endX, byte endY)
        {
            if (!OutputDisabled) { pDisplay.DrawLine(startX, startY, endX, endY); }
        }

        public void DrawPixel(byte xPos, byte yPos)
        {
            if (!OutputDisabled) { pDisplay.DrawPixel(xPos, yPos); }
        }

        public void Home()
        {
            if (!OutputDisabled) { pDisplay.Home(); }
        }

        public void InitializeLabel(byte labelID, byte leftPos, byte topPos, byte rightPos, byte bottomPos, JustificationVertical verticalJustification, JustificationHorizontal horizontalJustification, short fontId, byte backgroundColor, byte charSpace)
        {
            if (!OutputDisabled) { pDisplay.InitializeLabel(labelID, leftPos, topPos, rightPos, bottomPos, verticalJustification, horizontalJustification, fontId, backgroundColor, charSpace); }
        }

        public void InitializeTextWindow(byte windowId, byte left, byte top, byte right, byte bottom, short fontId, byte charSpace, byte lineSpace, byte scroll)
        {
            if (!OutputDisabled) { pDisplay.InitializeTextWindow(windowId, left, top, right, bottom, fontId, charSpace, lineSpace, scroll); }
        }

        public void Reset()
        {
            if (!OutputDisabled) { pDisplay.Reset(); }
        }

        public void ScrollScreen(byte leftPos, byte topPos, byte rightPos, byte bottomPos, byte moveX, byte moveY)
        {
            if (!OutputDisabled) { pDisplay.ScrollScreen(leftPos, topPos, rightPos, bottomPos, moveX, moveY); }
        }

        public void SetAutoScroll(bool isEnabled)
        {
            if (!OutputDisabled) { pDisplay.SetAutoScroll(isEnabled); }
        }

        public void SetBoxSpaceMode(bool clearExistingChar)
        {
            if (!OutputDisabled) { pDisplay.SetBoxSpaceMode(clearExistingChar); }
        }

        public void SetCurrentFont(short fontId)
        {
            if (!OutputDisabled) { pDisplay.SetCurrentFont(fontId); }
        }

        public void SetCursorCoordinate(byte xPosition, byte yPosition)
        {
            if (!OutputDisabled) { pDisplay.SetCursorCoordinate(xPosition, yPosition); }
        }

        public void SetCursorPosition(byte columnNumber, byte rowNumber)
        {
            if (!OutputDisabled) { pDisplay.SetCursorPosition(columnNumber, rowNumber); }
        }

        public void SetFontMetrics(byte lineMargin, byte topMargin, byte charSpace, byte lineSpace, byte scroll)
        {
            if (!OutputDisabled) { pDisplay.SetFontMetrics(lineMargin, topMargin, charSpace, lineSpace, scroll); }
        }

        public void SetLedBlinker(LedLocations location, bool enableBlinker)
        {
            if (!OutputDisabled) { pDisplay.SetLedBlinker(location, enableBlinker); }
        }

        public void SetLedIndicators(LedLocations location, LedColors color, bool forceUpdate = false)
        {
            if (!OutputDisabled) { pDisplay.SetLedIndicators(location, color, forceUpdate); }
        }

        public void SetTextWindow(byte windowId)
        {
            if (!OutputDisabled) { pDisplay.SetTextWindow(windowId); }
        }

        public void UpdateLabel(byte labelID, string labelText)
        {
            if (!OutputDisabled) { pDisplay.UpdateLabel(labelID, labelText); }
        }

        public void WriteText(string displayText)
        {
            if (!OutputDisabled) { pDisplay.WriteText(displayText); }
        }

        public byte MeasureBar(byte top, byte left, byte height, byte maxWidth, byte percent)
        {
            return pDisplay.MeasureBar(top, left, height, maxWidth, percent);
        }
    }

    internal class ProxyKeypadEventPreviewArgs : KeypadEventArgs
    {
        internal ProxyKeypadEventPreviewArgs(KeypadKeys key, bool filter = false) : base(key)
        {
            Filter = filter;
        }
        internal bool Filter { set; get; }
    }
}
